﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Threading;
using AvaloniaEdit;
using Newtonsoft.Json;
using ReactiveUI;
using TCP232.Models;
using TCP232.PublicMethod;
using TCP232.Views.UserControls;

namespace TCP232.ViewModels.UserControls;

[JsonObject(MemberSerialization.OptIn)]
public class ControlClientViewModel : ViewModelBase
{
    public ControlClientViewModel()
    {
        //bytes = bytes.Concat(bytes.GetCRC16()).ToArray();
        //SendingContent = bytes.ToHexString();
        PortNameList = GetPortNames();
        EncodingSelectedItem = EncodingList.FirstOrDefault();
        IP = UDPTargetSendingIP = GetLocalIP().FirstOrDefault();
        Port = UDPTargetSendingPort = 1024;
    }

    public ControlClientViewModel(ClientType clientType, ControlClient controlClient) : this()
    {
        ClientType = clientType;
        if (clientType == ClientType.SerialPort)
        {
            HeaderType = "串口";
            ControlSerialPort controlSerialPort = new ControlSerialPort();
            controlSerialPort.comboBoxPortName.PropertyChanged += (sender, e) =>
            {
                if (e.Property == ComboBox.IsDropDownOpenProperty)
                {
                    PortNameList = GetPortNames();
                }
            };
            CurrentControl = controlSerialPort;
            ReceiveType = "串口接收区";
            SettingsType = "串口设置";
            BtnContent = Const.Open;
        }
        else
        {
            HeaderType = "网口";
            CurrentControl = new ControlSocket();
            ReceiveType = "网络接收区";
            SettingsType = "网络设置";
            BtnContent = EthernetTypeSelectedItem == EthernetType.TCP_Server ? Const.StartListening : Const.Connect;
        }

        _controlClient = controlClient;
        CurrentControl.DataContext = this;
        _txtMessage = _controlClient.FindControl<TextEditor>("txtMessage");
        _txtSend = _controlClient.FindControl<TextBox>("txtSend");
    }

    uint _index;
    Task _task;
    Socket _socket;
    SerialPort _serialPort = new SerialPort();
    ControlClient _controlClient;
    TextEditor _txtMessage = new TextEditor();
    TextBox _txtSend = new TextBox();
    // System.Timers.Timer _timer = new System.Timers.Timer(1000);
    ConcurrentDictionary<string, Socket> _clientSockets = new ConcurrentDictionary<string, Socket>();

    private ClientType _clientType;

    public ClientType ClientType
    {
        get => _clientType;
        set
        {
            _clientType = value;
            this.RaisePropertyChanged(nameof(ClientType));
        }
    }

    private ObservableCollection<string> _portNameList;

    public ObservableCollection<string> PortNameList
    {
        get => _portNameList;
        set
        {
            _portNameList = value;
            this.RaisePropertyChanged(nameof(PortNameList));
        }
    }

    private bool _connectIsEnabled = true;

    public bool ConnectIsEnabled
    {
        get => _connectIsEnabled;
        set
        {
            _connectIsEnabled = value;
            this.RaisePropertyChanged(nameof(ConnectIsEnabled));
        }
    }

    private bool _returnIsSend;
    [JsonProperty]
    public bool ReturnIsSend
    {
        get => _returnIsSend;
        set
        {
            _returnIsSend = value;
            if (value && _txtSend.IsEnabled)
            {
                _txtSend.Focus();
            }

            this.RaisePropertyChanged(nameof(ReturnIsSend));
        }
    }

    public List<int> BaudRateList { get; set; } = new List<int>() { 110, 300, 600, 1200, 2400, 4600, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200, 128000, 256000, 460800 };

    public List<Parity> ParityList { get; set; } = new List<Parity>() { Parity.None, Parity.Odd, Parity.Even, Parity.Mark, Parity.Space };

    public List<int> DataBitsList { get; set; } = new List<int>() { 5, 6, 7, 8 };

    public List<StopBits> StopBitsList { get; set; } = new List<StopBits>() { StopBits.None, StopBits.One, StopBits.Two, StopBits.OnePointFive };

    public List<EthernetType> EthernetTypeList { get; set; } = new List<EthernetType>() { EthernetType.UDP, EthernetType.TCP_Server, EthernetType.TCP_Client };

    public List<string> EncodingList { get; set; } = new List<string>() { "UTF-8", "ASCII", "Default", "ISO-8859-1", "Unicode", "BigEndianUnicode", "UTF-32" };

    //private ObservableCollection<Encoding> _encodingList = new (new List<Encoding>() { Encoding.UTF8, Encoding.ASCII, Encoding.BigEndianUnicode, Encoding.Default, Encoding.Latin1, Encoding.Unicode, Encoding.UTF32 });

    //public ObservableCollection<Encoding> EncodingList
    //{
    //    get => _encodingList;
    //    set
    //    {
    //        _encodingList = value;
    //        this.RaisePropertyChanged(nameof(EncodingList));
    //    }
    //}

    Encoding CurrentEncoding => EncodingSelectedItem switch
    {
        "UTF-8" => Encoding.UTF8,
        "ASCII" => Encoding.ASCII,
        "Default" => Encoding.Default,
        "ISO-8859-1" => Encoding.Latin1,
        "Unicode" => Encoding.Unicode,
        "BigEndianUnicode" => Encoding.BigEndianUnicode,
        "UTF-32" => Encoding.UTF32,
        _ => Encoding.UTF8
    };

    private string _encodingSelectedItem;
    [JsonProperty]
    public string EncodingSelectedItem
    {
        get => _encodingSelectedItem;
        set
        {
            _encodingSelectedItem = value;
            if (_serialPort.Encoding != CurrentEncoding)
            {
                _serialPort.Encoding = CurrentEncoding;
            }

            this.RaisePropertyChanged(nameof(EncodingSelectedItem));
        }
    }

    private string _headerType;

    public string HeaderType
    {
        get => _headerType;
        set
        {
            _headerType = value;
            this.RaisePropertyChanged(nameof(HeaderType));
        }
    }

    private UserControl _currentControl;

    public UserControl CurrentControl
    {
        get => _currentControl;
        set
        {
            _currentControl = value;
            this.RaisePropertyChanged(nameof(CurrentControl));
        }
    }

    private string _receiveType;

    public string ReceiveType
    {
        get => _receiveType;
        set
        {
            _receiveType = value;
            this.RaisePropertyChanged(nameof(ReceiveType));
        }
    }

    private string _settingsType;

    public string SettingsType
    {
        get => _settingsType;
        set
        {
            _settingsType = value;
            this.RaisePropertyChanged(nameof(SettingsType));
        }
    }

    private string _ip;

    public string IP
    {
        get => _ip;
        set
        {
            _ip = value;
            this.RaisePropertyChanged(nameof(IP));
        }
    }

    private int _port;
    [JsonProperty]
    public int Port
    {
        get => _port;
        set
        {
            _port = value;
            this.RaisePropertyChanged(nameof(Port));
        }
    }

    private EthernetType _ethernetTypeSelectedItem;
    [JsonProperty]
    public EthernetType EthernetTypeSelectedItem
    {
        get => _ethernetTypeSelectedItem;
        set
        {
            _ethernetTypeSelectedItem = value;
            if (BtnContent != Const.DisConnect)
            {
                BtnContent = value == EthernetType.TCP_Server ? Const.StartListening : Const.Connect;
            }

            this.RaisePropertyChanged(nameof(EthernetTypeSelectedItem));
        }
    }

    private string _portNameSelectedItem;
    [JsonProperty]
    public string PortNameSelectedItem
    {
        get => _portNameSelectedItem;
        set
        {
            if (!PortNameList.Contains(value))
            {
                value = PortNameList.FirstOrDefault();
            }
            _portNameSelectedItem = value;
            this.RaisePropertyChanged(nameof(PortNameSelectedItem));
        }
    }

    private int _baudRateSelectedItem = 9600;
    [JsonProperty]
    public int BaudRateSelectedItem
    {
        get => _baudRateSelectedItem;
        set
        {
            _baudRateSelectedItem = value;
            this.RaisePropertyChanged(nameof(BaudRateSelectedItem));
        }
    }

    private Parity _paritySelectedItem = Parity.None;
    [JsonProperty]
    public Parity ParitySelectedItem
    {
        get => _paritySelectedItem;
        set
        {
            _paritySelectedItem = value;
            this.RaisePropertyChanged(nameof(ParitySelectedItem));
        }
    }

    private int _dataBitsSelectedItem = 8;
    [JsonProperty]
    public int DataBitsSelectedItem
    {
        get => _dataBitsSelectedItem;
        set
        {
            _dataBitsSelectedItem = value;
            this.RaisePropertyChanged(nameof(DataBitsSelectedItem));
        }
    }

    private StopBits _stopBitsSelectedItem = StopBits.One;
    [JsonProperty]
    public StopBits StopBitsSelectedItem
    {
        get => _stopBitsSelectedItem;
        set
        {
            _stopBitsSelectedItem = value;
            this.RaisePropertyChanged(nameof(StopBitsSelectedItem));
        }
    }

    private string _errorMessage;

    public string ErrorMessage
    {
        get => _errorMessage;
        set
        {
            _errorMessage = /*"异常：+"*/ value;
            this.RaisePropertyChanged(nameof(ErrorMessage));
        }
    }

    private string _btnContent;

    public string BtnContent
    {
        get => _btnContent;
        set
        {
            _btnContent = value;
            DisConnectImageIsVisible = value == Const.DisConnect;
            this.RaisePropertyChanged(nameof(BtnContent));
        }
    }

    private string _sendingBtnContent = Const.Send;

    public string SendingBtnContent
    {
        get => _sendingBtnContent;
        set
        {
            _sendingBtnContent = value;
            this.RaisePropertyChanged(nameof(SendingBtnContent));
        }
    }

    private string _sendingContent;

    public string SendingContent
    {
        get => _sendingContent;
        set
        {
            _sendingContent = value;
            this.RaisePropertyChanged(nameof(SendingContent));
        }
    }

    private int _sentingBytesCount;

    public int SentBytesCount
    {
        get => _sentingBytesCount;
        set
        {
            _sentingBytesCount = value;
            this.RaisePropertyChanged(nameof(SentBytesCount));
        }
    }

    private int _receivedBytesCount;

    public int ReceivedBytesCount
    {
        get => _receivedBytesCount;
        set
        {
            _receivedBytesCount = value;
            this.RaisePropertyChanged(nameof(ReceivedBytesCount));
        }
    }

    private ObservableCollection<string> _clientList = new ObservableCollection<string>();

    public ObservableCollection<string> ClientList
    {
        get => _clientList;
        set
        {
            _clientList = value;
            this.RaisePropertyChanged(nameof(ClientList));
        }
    }

    private ObservableCollection<HistoryDataModel> _historyData = new ObservableCollection<HistoryDataModel>();

    public ObservableCollection<HistoryDataModel> HistoryData
    {
        get => _historyData;
        set
        {
            _historyData = value;
            this.RaisePropertyChanged(nameof(HistoryData));
        }
    }

    private string _clientSelectedItem;

    public string ClientSelectedItem
    {
        get => _clientSelectedItem;
        set
        {
            _clientSelectedItem = value;
            this.RaisePropertyChanged(nameof(ClientSelectedItem));
        }
    }

    private string _localEndPoint;

    public string LocalEndPoint
    {
        get => _localEndPoint;
        set
        {
            _localEndPoint = value;
            this.RaisePropertyChanged(nameof(LocalEndPoint));
        }
    }

    private bool _isAutoWrap;
    [JsonProperty]
    public bool IsAutoWrap
    {
        get => _isAutoWrap;
        set
        {
            _isAutoWrap = value;
            this.RaisePropertyChanged(nameof(IsAutoWrap));
        }
    }

    private bool _receiveIsHexShow;
    [JsonProperty]
    public bool ReceiveIsHexShow
    {
        get => _receiveIsHexShow;
        set
        {
            _receiveIsHexShow = value;
            this.RaisePropertyChanged(nameof(ReceiveIsHexShow));
        }
    }

    private bool _receiveIsAddTime;
    [JsonProperty]
    public bool ReceiveIsAddTime
    {
        get => _receiveIsAddTime;
        set
        {
            _receiveIsAddTime = value;
            this.RaisePropertyChanged(nameof(ReceiveIsAddTime));
        }
    }

    private bool _sentIsClear;
    [JsonProperty]
    public bool SentIsClear
    {
        get => _sentIsClear;
        set
        {
            _sentIsClear = value;
            this.RaisePropertyChanged(nameof(SentIsClear));
        }
    }

    private bool _sendingIsHex;
    [JsonProperty]
    public bool SendingIsHex
    {
        get => _sendingIsHex;
        set
        {
            _sendingIsHex = value;
            if (!string.IsNullOrEmpty(SendingContent))
            {
                SendingContent = value
                    ? CurrentEncoding.GetBytes(SendingContent).ToHexString()
                    : CurrentEncoding.GetString(SendingContent.ToBytes());
            }

            this.RaisePropertyChanged(nameof(SendingIsHex));
        }
    }

    private bool _sendingIsAddTime;
    [JsonProperty]
    public bool SendingIsAddTime
    {
        get => _sendingIsAddTime;
        set
        {
            _sendingIsAddTime = value;
            this.RaisePropertyChanged(nameof(SendingIsAddTime));
        }
    }

    private bool _autoSendingIsEnabled = true;

    public bool AutoSendingIsEnabled
    {
        get => _autoSendingIsEnabled;
        set
        {
            _autoSendingIsEnabled = value;
            this.RaisePropertyChanged(nameof(AutoSendingIsEnabled));
        }
    }

    private bool _isCirculateSending;
    [JsonProperty]
    public bool IsCirculateSending
    {
        get => _isCirculateSending;
        set
        {
            _isCirculateSending = value;
            this.RaisePropertyChanged(nameof(IsCirculateSending));
        }
    }

    private uint _sendingInterval = 1000;
    [JsonProperty]
    public uint SendingInterval
    {
        get => _sendingInterval;
        set
        {
            _sendingInterval = value;
            this.RaisePropertyChanged(nameof(SendingInterval));
        }
    }

    private string _udpTargetSendingIP;

    public string UDPTargetSendingIP
    {
        get => _udpTargetSendingIP;
        set
        {
            _udpTargetSendingIP = value;
            this.RaisePropertyChanged(nameof(UDPTargetSendingIP));
        }
    }

    private int _udpTargetSendingPort;
    [JsonProperty]
    public int UDPTargetSendingPort
    {
        get => _udpTargetSendingPort;
        set
        {
            _udpTargetSendingPort = value;
            this.RaisePropertyChanged(nameof(UDPTargetSendingPort));
        }
    }

    private bool _udpSendingAreaIsVisible;

    public bool UDPSendingAreaIsVisible
    {
        get => _udpSendingAreaIsVisible;
        set
        {
            _udpSendingAreaIsVisible = value;
            this.RaisePropertyChanged(nameof(UDPSendingAreaIsVisible));
        }
    }

    private bool _localEndPointAreaIsVisible;

    public bool LocalEndPointAreaIsVisible
    {
        get => _localEndPointAreaIsVisible;
        set
        {
            _localEndPointAreaIsVisible = value;
            this.RaisePropertyChanged(nameof(LocalEndPointAreaIsVisible));
        }
    }

    private bool _clientAreaIsVisible;

    public bool ClientAreaIsVisible
    {
        get => _clientAreaIsVisible;
        set
        {
            _clientAreaIsVisible = value;
            this.RaisePropertyChanged(nameof(ClientAreaIsVisible));
        }
    }

    private bool _disConnectImageIsVisible;

    public bool DisConnectImageIsVisible
    {
        get => _disConnectImageIsVisible;
        set
        {
            _disConnectImageIsVisible = value;
            this.RaisePropertyChanged(nameof(DisConnectImageIsVisible));
        }
    }

    ObservableCollection<string> GetPortNames()
    {
        try
        {
            return new ObservableCollection<string>(SerialPort.GetPortNames());
        }
        catch (Exception ex)
        {
            ErrorMessage = ex.Message;
            return new ObservableCollection<string>();
        }
    }

    public async void SaveReceiveContent()
    {
        try
        {
            //var s = await new OpenFileDialog() { AllowMultiple = true }.ShowAsync(App.mainWindowViewModel.MainWindow);
            //OpenFolderDialog openFolderDialog = new OpenFolderDialog(); 
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filters.Add(new FileDialogFilter { Name = "文本文档", Extensions = { "txt" } });
            var filePath = await saveFileDialog.ShowAsync(MainWindowViewModel.Instance.MainWindow);

            if (!string.IsNullOrEmpty(filePath))
            {
                using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write);
                using var streamWriter = new StreamWriter(fileStream, Encoding.UTF8);
                streamWriter.Write(_txtMessage.Text);
                MessageTip.Show($"接收区的数据保存到：{filePath}成功");
            }
        }
        catch (Exception ex)
        {
            MessageTip.ShowError("保存文件失败：" + Environment.NewLine + ex);
        }
    }

    public void ClearReceiveContent()
    {
        _txtMessage.Clear();
    }

    public void CountZero()
    {
        SentBytesCount = ReceivedBytesCount = 0;
    }

    public void ClearSendingContent()
    {
        SendingContent = string.Empty;
    }

    Task StartLongTask(Action action)
    {
        return Task.Factory.StartNew(action, TaskCreationOptions.LongRunning);

        //Task.Run(action);
        //Thread thread = new Thread(new ThreadStart(action));
        //thread.IsBackground = true;
        //thread.Start();
    }

    public void Open()
    {
        Task.Run(() =>
        {
            try
            {
                if (BtnContent == Const.Connecting)
                {
                    return;
                }

                if (BtnContent == Const.DisConnect)
                {
                    DisConnect();
                    return;
                }

                if (ClientType == ClientType.SerialPort)
                {
                    DisConnectWithSerialPort();
                    _serialPort.PortName = PortNameSelectedItem;
                    _serialPort.BaudRate = BaudRateSelectedItem;
                    _serialPort.Parity = ParitySelectedItem; //奇偶检验
                    _serialPort.StopBits = StopBitsSelectedItem; //停止位
                    _serialPort.DataBits = DataBitsSelectedItem; //数据位
                    _serialPort.Open();
                    _serialPort.DataReceived -= DataReceived;
                    _serialPort.DataReceived += DataReceived;
                    if (_serialPort.IsOpen)
                    {
                        BtnContent = Const.DisConnect;
                        ConnectIsEnabled = false;
                    }
                    else
                    {
                        BtnContent = Const.Open;
                    }
                }
                else
                {
                    DisConnectWithSocket();
                    IPEndPoint point = new IPEndPoint(IPAddress.Parse(IP), Port);
                    if (EthernetTypeSelectedItem == EthernetType.TCP_Server)
                    {
                        _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        _socket.Bind(point);
                        _socket.Listen();
                        if (_socket.IsBound)
                        {
                            StartLongTask(() =>
                            {
                                while (true)
                                {
                                    try
                                    {
                                        Socket socket = _socket.Accept();
                                        string remoteEndPoint = socket.RemoteEndPoint?.ToString();
                                        _clientSockets.TryAdd(remoteEndPoint, socket);
                                        if (!ClientList.Contains(Const.AllConnections))
                                        {
                                            ClientList.Add(Const.AllConnections);
                                        }

                                        ClientList.Add(remoteEndPoint);
                                        ClientSelectedItem = remoteEndPoint;

                                        StartLongTask(() => Recive(socket, EthernetType.TCP_Server));
                                    }
                                    catch (Exception ex)
                                    {
                                        ErrorMessage = ex.Message;
                                        break;
                                    }
                                }
                            });
                            ConnectIsEnabled = false;
                            ClientAreaIsVisible = true;
                            LocalEndPointAreaIsVisible = false;
                            UDPSendingAreaIsVisible = false;
                            BtnContent = Const.DisConnect;
                        }
                        else
                        {
                            BtnContent = Const.StartListening;
                            ErrorMessage = "开始监听服务失败";
                        }
                    }
                    else if (EthernetTypeSelectedItem == EthernetType.TCP_Client)
                    {
                        _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        Task.Run(() => CheckConnectTimeout());
                        ConnectIsEnabled = false;
                        _socket.Connect(point);

                        ClientAreaIsVisible = false;
                        LocalEndPointAreaIsVisible = true;
                        UDPSendingAreaIsVisible = false;
                        LocalEndPoint = _socket.LocalEndPoint?.ToString();
                        StartLongTask(() => Recive(_socket, EthernetType.TCP_Client));
                    }
                    else
                    {
                        _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                        _socket.Bind(point);
                        if (_socket.IsBound)
                        {
                            StartLongTask(() => Recive(_socket, EthernetType.UDP));
                            ConnectIsEnabled = false;
                            ClientAreaIsVisible = false;
                            LocalEndPointAreaIsVisible = false;
                            UDPSendingAreaIsVisible = true;
                            BtnContent = Const.DisConnect;
                        }
                        else
                        {
                            BtnContent = Const.Connect;
                            ErrorMessage = "开启UDP服务失败";
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ErrorMessage = ex.Message;
                DisConnect();
            }
        });
    }

    void ShowNotOpen()
    {
        if (ClientType == ClientType.SerialPort)
        {
            ErrorMessage = "无法发送，串口未打开或连接已断开";
        }
        else
        {
            ErrorMessage = "无法发送，Socket未连接或连接已断开";
        }
    }

    public void EnterKeyDown(TextBox textBox)
    {
        if (ReturnIsSend)
        {
            Send();
        }
        else
        {
            var args = new KeyEventArgs
            {
                RoutedEvent = InputElement.KeyDownEvent,
                Key = Key.Enter,
                //KeyModifiers= KeyModifiers.
                Source = textBox
            };

            textBox.RaiseEvent(args);
        }
    }

    void UpdateAutoSendingStatus(bool isSending)
    {
        SendingBtnContent = isSending ? Const.Send : Const.StopSend;
        AutoSendingIsEnabled = isSending;
    }

    public void Send()
    {
        try
        {
            if (string.IsNullOrEmpty(SendingContent))
            {
                if (!_txtSend.IsFocused)
                {
                    _txtSend.Focus();
                }

                ErrorMessage = "发送的内容为空，无法发送";
                return;
            }

            if (SendingBtnContent == Const.StopSend)
            {
                UpdateAutoSendingStatus(true);
            }
            else
            {
                if (IsCirculateSending)
                {
                    if (_task is not { Status: TaskStatus.Running } && SendData())
                    {
                        _txtMessage.Focus();
                        UpdateAutoSendingStatus(false);
                        _task = StartLongTask(() =>
                        {
                            Stopwatch stopwatch = Stopwatch.StartNew();
                            while (SendingBtnContent == Const.StopSend)
                            {
                                try
                                {
                                    if (stopwatch.ElapsedMilliseconds >= SendingInterval)
                                    {
                                        stopwatch.Restart();
                                        if (!SendData())
                                        {
                                            break;
                                        }
                                    }
                                    Thread.Sleep(1);
                                }
                                catch (Exception ex)
                                {
                                    ErrorMessage = ex.Message;
                                    break;
                                }
                            }
                            stopwatch.Stop();
                            ErrorMessage = "自动循环发送已结束";
                            UpdateAutoSendingStatus(true);
                        });
                    }
                }
                else
                {
                    SendData();
                }
            }
        }
        catch (Exception ex)
        {
            ErrorMessage = ex.Message;
        }
    }

    bool SendData()
    {
        byte[] data = SendingIsHex ? SendingContent.ToBytes() : CurrentEncoding.GetBytes(SendingContent);

        int count = 0;
        string source = null;
        if (ClientType == ClientType.SerialPort)
        {
            if (!_serialPort.IsOpen)
            {
                DisConnect();
                ShowNotOpen();
                return false;
            }

            _serialPort.Write(data, 0, data.Length);
            count = data.Length;
            source = _serialPort.PortName;
        }
        else
        {
            if (EthernetTypeSelectedItem == EthernetType.TCP_Server)
            {
                source = ClientSelectedItem;
                if (ClientSelectedItem == Const.AllConnections)
                {
                    List<string> endPoint = new List<string>();
                    foreach (var item in _clientSockets.Values)
                    {
                        count += item.Write(data, ShowNotOpen);
                        endPoint.Add(item.RemoteEndPoint?.ToString());
                    }
                    source = string.Join(";", endPoint);
                }
                else
                {
                    if (string.IsNullOrEmpty(ClientSelectedItem))
                    {
                        ShowNotOpen();
                    }
                    else
                    {
                        if (_clientSockets.ContainsKey(ClientSelectedItem))
                        {
                            count = _clientSockets[ClientSelectedItem].Write(data, ShowNotOpen);
                        }
                        else
                        {
                            ErrorMessage = "无法发送，选中的连接对象未连接";
                        }
                    }
                }
            }
            else if (EthernetTypeSelectedItem == EthernetType.TCP_Client)
            {
                count = _socket.Write(data, ShowNotOpen);
                source = _socket?.RemoteEndPoint?.ToString();
            }
            else
            {
                if (_socket == null)
                {
                    ShowNotOpen();
                }
                else
                {
                    IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(UDPTargetSendingIP), UDPTargetSendingPort);
                    //count = _socket.SendTo(data, 0, data.Length, SocketFlags.None, remoteEP);
                    count = _socket.SendTo(data, iPEndPoint);
                    source = iPEndPoint.ToString();
                }
            }
        }

        if (SentIsClear)
        {
            SendingContent = string.Empty;
        }

        if (count > 0)
        {
            ErrorMessage = $"发送完成，时间：{DateTime.Now:HH:mm:ss.fff}";
            SentBytesCount += count;
            ShowMessage(data, source, false);
        }

        return count > 0;
    }

    void DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        int length = _serialPort.BytesToRead;
        ReceivedBytesCount += length;
        byte[] buff = new byte[length];
        _serialPort.Read(buff, 0, length);
        var serialPort = (SerialPort)sender;
        ShowMessage(buff, serialPort.PortName, true);
    }

    public void Recive(Socket socket, EthernetType ethernetType)
    {
        string socketClient = socket.RemoteEndPoint?.ToString();

        while (true)
        {
            try
            {
                int length;
                byte[] buff;
                EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
                if (ethernetType == EthernetType.UDP)
                {
                    buff = new byte[ushort.MaxValue + 1];
                    length = socket.ReceiveFrom(buff, ref endPoint);
                }
                else
                {
                    buff = Array.Empty<byte>();
                    var data = new byte[1024];
                    length = socket.Receive(data);
                    buff = buff.Concat(data).ToArray();

                    if (socket.Available > 0)
                    {
                        byte[] second = new byte[socket.Available];
                        socket.Receive(second);
                        buff = buff.Concat(second).ToArray();
                        length += second.Length;
                    }
                }

                if (length < 1)
                {
                    if (ethernetType == EthernetType.UDP)
                    {
                        continue;
                    }
                    ErrorMessage = $"与远程主机[{socketClient}]的连接已被中断";
                    break;
                }

                ReceivedBytesCount += length;
                buff = buff.Take(length).ToArray();

                socketClient = ethernetType == EthernetType.UDP ? endPoint.ToString() : socketClient;
                ShowMessage(buff, socketClient, true);
            }
            catch (Exception ex)
            {
                if (ethernetType == EthernetType.UDP && _socket != null)
                {
                    if (ex is SocketException socketException && socketException.ErrorCode == 10054)
                    {
                        ErrorMessage = "UDP数据可能发送不成功";//10054
                    }
                    else
                    {
                        ErrorMessage = ex.Message;
                    }
                }
                else
                {
                    //errorcode:10040
                    ErrorMessage = $"与远程主机{(ethernetType == EthernetType.UDP ? null : $"[{socketClient}]")}的连接已中断，{ex.Message}";
                    break;
                }
            }
        }

        if (ethernetType == EthernetType.TCP_Server)
        {
            DisConnectWithClient(socketClient);
        }
        else
        {
            DisConnect();
        }
    }

    //public void LoadingRowCommand(DataGridRowEventArgs e)
    //{
    //    e.Row.Header = e.Row.GetIndex() + 1;
    //}

    string GetStringType(bool flag)
    {
        return flag ? "HEX" : "String";
    }

    void AddHistoryData(DateTime dateTime, string source, bool isReceive, bool isHexShow, string data)
    {
        HistoryData.Add(new HistoryDataModel() { Index = ++_index, Date = dateTime, Source = source, IsReceive = isReceive, ReceiveType = GetStringType(isHexShow), Content = data });
    }

    void ShowMessage(byte[] bytes, string source, bool isReceive)
    {
        if (bytes == null || bytes.Length == 0)
        {
            return;
        }

        DateTime dateTime = DateTime.Now;
        string date = $"[{dateTime:yyyy/MM/dd HH:mm:ss.fff}]";
        string message = CurrentEncoding.GetString(bytes);
        Dispatcher.UIThread.InvokeAsync(async () =>
        {
            string newLine = Environment.NewLine;
            void CheckNewLine()
            {
                if (!string.IsNullOrEmpty(_txtMessage.Text) && _txtMessage.Text[^1] != '\n')
                {
                    message = newLine + message;
                }
            }

            if (isReceive)
            {
                var data = ReceiveIsHexShow ? bytes.ToHexString() : message;
                AddHistoryData(dateTime, source, true, ReceiveIsHexShow, data);
                message = data;
                if (IsAutoWrap)
                {
                    data += newLine;
                    message = data;
                    CheckNewLine();
                }

                if (ReceiveIsAddTime)
                {
                    message = $"{date}[Receive {GetStringType(ReceiveIsHexShow)} from {source}]{data}{(IsAutoWrap ? null : newLine)}";
                    CheckNewLine();
                }
            }
            else
            {
                var data = SendingIsHex ? bytes.ToHexString() : message;
                AddHistoryData(dateTime, source, false, SendingIsHex, data);

                if (SendingIsAddTime)
                {
                    message = $"{date}[Send {GetStringType(SendingIsHex)} to {source}]{data}{newLine}";
                    CheckNewLine();
                }
                else
                {
                    return;
                }
            }

            _txtMessage.AppendText(message);
            if (!_txtMessage.IsPointerOver)
            {
                await Task.Delay(40);
                //Thread.Sleep(10);
                //txtMessage. += delegate
                //{
                //Debug.WriteLine(txtMessage.Text);
                //txtMessage.SelectionStart = txtMessage.Text.Length;
                //txtMessage?.ScrollToEnd();

                _txtMessage.ScrollToEnd();
                //};

                //var scrollViewer = (ScrollViewer)txtSend.FindDescendantOfType<ScrollViewer>();

                //// 滚动到最底部
                //scrollViewer.Offset = new Vector(0, scrollViewer.Extent.Height - scrollViewer.Viewport.Height);
                //txtMessage.PageDown();
                //var parent = txtMessage.GetVisualChildren();


                //txtMessage?.ScrollToVerticalOffset(double.MaxValue);

                //foreach (var item in parent)
                //{
                //    var c = item.GetVisualChildren();
                //    foreach (var a in c)
                //    {
                //        if (a is ScrollViewer scrollViewer)
                //        {
                //            scrollViewer.ScrollToEnd();
                //            //scrollViewer.LayoutUpdated += (sender, args) => scrollViewer.ScrollToEnd();
                //        }
                //        //Debug.WriteLine(a.GetType().FullName);
                //    }

                //}
                //txtMessage.Caret.InsertMode = CaretInsertMode.Overwrite;
                //txtMessage.Caret.InsertMode = CaretInsertMode.Insert;
                //txtMessage?.ScrollToEnd();


                //txtMessage.SelectionStart = txtMessage.Text.Length + 1;


                //txtMessage?.ScrollToLine(txtMessage.Document.LineCount - 1);
                //txtMessage?.ScrollToVerticalOffset(txtMessage.LineCount,0);
                //Debug.WriteLine(txtMessage.LineCount);
            }
        });
    }

    void CheckConnectTimeout(int timeout = 3000)
    {
        BtnContent = Const.Connecting;
        Stopwatch stopwatch = Stopwatch.StartNew();
        while (timeout > stopwatch.ElapsedMilliseconds)
        {
            if (_socket == null)
            {
                BtnContent = Const.Connect;
                stopwatch.Stop();
                return;
            }

            if (_socket.IsConnected())
            {
                BtnContent = Const.DisConnect;
                break;
            }
            else
            {
                Thread.Sleep(10);
            }
        }

        stopwatch.Stop();
        if (timeout <= stopwatch.ElapsedMilliseconds && !_socket.IsConnected())
        {
            DisConnect();
            ErrorMessage = $"连接超时[{timeout}ms]，请检查网口或IP配置";
        }
    }

    void DisConnect()
    {
        try
        {
            ConnectIsEnabled = true;
            if (ClientType == ClientType.SerialPort)
            {
                DisConnectWithSerialPort();
                BtnContent = Const.Open;
            }
            else
            {
                LocalEndPointAreaIsVisible = ClientAreaIsVisible = UDPSendingAreaIsVisible = false;
                BtnContent = EthernetTypeSelectedItem == EthernetType.TCP_Server ? Const.StartListening : Const.Connect;
                DisConnectWithSocket();
            }
        }
        catch (Exception ex)
        {
            ErrorMessage = ex.Message;
        }
    }

    void DisConnectWithSerialPort()
    {
        _serialPort.Close();
        PortNameList = GetPortNames();
    }

    void DisConnectWithSocket()
    {
        if (EthernetTypeSelectedItem == EthernetType.TCP_Server)
        {
            foreach (var item in _clientSockets.Values)
            {
                item?.DisConnect();
            }
        }

        _socket?.DisConnect();
        _socket = null;
    }

    public void DisConnectWithClient()
    {
        if (string.IsNullOrEmpty(ClientSelectedItem))
        {
            return;
        }

        if (ClientSelectedItem == Const.AllConnections)
        {
            foreach (var item in _clientSockets)
            {
                DisConnectWithClient(item.Key);
            }
        }
        else
        {
            DisConnectWithClient(ClientSelectedItem);
        }
    }

    void DisConnectWithClient(string remoteEndPoint)
    {
        if (_clientSockets.ContainsKey(remoteEndPoint))
        {
            _clientSockets[remoteEndPoint]?.DisConnect();
            _clientSockets[remoteEndPoint] = null;
            _clientSockets.TryRemove(remoteEndPoint, out _);
        }

        if (_clientSockets.IsEmpty)
        {
            ClientList.Clear();
        }
        else
        {
            ClientList.Remove(remoteEndPoint);
            ClientSelectedItem = ClientList.FirstOrDefault();
        }
    }

    List<string> GetLocalIP()
    {
        List<string> ips = new List<string>();
        try
        {
            string hostName = Dns.GetHostName(); //得到主机名
            IPHostEntry ipEntry = Dns.GetHostEntry(hostName);
            foreach (var item in ipEntry.AddressList)
            {
                if (item.AddressFamily == AddressFamily.InterNetwork)
                {
                    ips.Add(item.ToString());
                }
            }
        }
        catch (Exception ex)
        {
            ErrorMessage = ex.Message;
        }

        return ips;
    }
}